﻿using System.Security.Cryptography;
using System.Text;

namespace AuSys.Utils.Cryptography
{
    /// <summary>
    /// MD5工具类
    /// </summary>
    public static class MD5Helper
    {
        /// <summary>
        /// 获取字符串的MD5值（32位小写）
        /// </summary>
        /// <param name="input">目标字符串</param>
        /// <returns>MD5值</returns>
        public static string GetMD5(this string input)
        {
            input ??= "";
            byte[] data = MD5.HashData(Encoding.UTF8.GetBytes(input));
            return BytesToStr(data);
        }
        /// <summary>
        /// 获取Stream的MD5值，同时把Stream的数据写到另一个Stream里（不耗内存）
        /// </summary>
        /// <param name="source">来源Stream</param>
        /// <param name="destination">去向Stream</param>
        /// <returns>MD5值</returns>
        public static string GetMD5AndCopyTo(this Stream source, Stream destination)
        {
            using MD5 md5 = MD5.Create();
            byte[] buffer = new byte[8192];
            int bytesRead;

            while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
            {
                destination.Write(buffer, 0, bytesRead);
                md5.TransformBlock(buffer, 0, bytesRead, null, 0);
            }
            md5.TransformFinalBlock(buffer, 0, 0);
            byte[] hashBytes = md5.Hash ?? [];
            return BytesToStr(hashBytes);
        }
        /// <summary>
        /// 获取Stream的MD5值（会把Stream读到头）
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string GetMD5(this Stream s)
        {
            byte[] data = MD5.HashData(s);
            return BytesToStr(data);
        }

        private static string BytesToStr(byte[] data)
        {
            StringBuilder sBuilder = new();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }
    }
}

